package com.wing.user.controller.admin;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wing.common.exception.BusinessException;
import com.wing.common.utils.JsonResult;
import com.wing.common.utils.PageResult;
import com.wing.user.model.entity.CompanyInfo;
import com.wing.user.model.entity.Department;
import com.wing.user.model.entity.User;
import com.wing.user.model.request.DepartmentForm;
import com.wing.user.model.response.DepartmentVO;
import com.wing.user.service.CompanyInfoService;
import com.wing.user.service.DepartmentService;
import com.wing.user.service.UserService;
import com.wing.user.utils.ExcelUtils;
import com.wing.web.annotation.RequestObjectFieldIgnore;
import com.wing.web.excel.DepartmentExcelIn;
import com.wing.web.excel.DownExcelUtil;
import com.wing.web.excel.ExcelUtil;
import com.wing.web.excel.UseInventoryUserExcelIn;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 *
 * @author
 */
@Slf4j
@Validated
@Api(value = "Admin-部门架构管理", tags = "#/user/department")
@RestController("departmentController")
@RequestMapping("/user/admin/department")
@RequiredArgsConstructor
public class DepartmentController {

    private final DepartmentService departmentService;
    private final CompanyInfoService companyInfoService;
    private final UserService userService;

    @ApiOperation(value = "查询所有部门架构", notes = "搜索")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "第几页", defaultValue = "1", example = "1", dataType = "Integer", paramType = "query")
            ,@ApiImplicitParam(name = "limit", value = "每页多少条", defaultValue = "10", example = "10", dataType = "Integer", paramType = "query")
            ,@ApiImplicitParam(name = "sort", value="排序字段名", defaultValue = "create_time", example = "create_time", dataType = "String", paramType = "query")
            ,@ApiImplicitParam(name = "order", value="排序规则(asc:正序, desc:倒序)", defaultValue = "asc", example = "asc", dataType = "String", paramType = "query")
            ,@ApiImplicitParam(name = "companyInfoId", value = "企业ID", defaultValue = "", example = "", dataType = "Long", paramType = "query")
            ,@ApiImplicitParam(name = "isFinal", value = "是否终级部门", defaultValue = "", example = "", dataType = "Boolean", paramType = "query")
            ,@ApiImplicitParam(name = "name", value = "名称", defaultValue = "", example = "", dataType = "String", paramType = "query")
            ,@ApiImplicitParam(name = "principal", value = "负责人", defaultValue = "", example = "", dataType = "Long", paramType = "query")
    })
    @GetMapping("/list")
    public PageResult<DepartmentVO> list(
            @RequestParam(defaultValue = "1") Integer page
            ,@RequestParam(defaultValue = "10") Integer limit
            ,@RequestParam(defaultValue = "create_time") String sort
            ,@RequestParam(defaultValue = "asc") String order
            ,Long companyInfoId
            ,Boolean isFinal
            ,String name
            ,String principalName
    ){
        Page<Department> pg = new Page<>(page, limit);
        Map paramMap=new HashMap();
        paramMap.put("sort",StrUtil.toUnderlineCase(sort));
        paramMap.put("order",StrUtil.toUnderlineCase(order));
        if (companyInfoId != null){
            paramMap.put("companyInfoId", companyInfoId);
        }
        if (isFinal != null){
            paramMap.put("isFinal", isFinal);
        }
        if (StringUtils.isNotBlank(name)) {
            paramMap.put("name", name);
        }
        if (StringUtils.isNotBlank(principalName)){
            paramMap.put("principalName", principalName);
        }
        IPage<DepartmentVO> list = departmentService.pageList4app(pg,paramMap);
        return new PageResult<>(list.getRecords(), list.getTotal());
    }

    @GetMapping("/getDepartmentVOById")
    public JsonResult<DepartmentVO> getDepartmentVOById(@RequestParam(name = "departmentId") Long departmentId){
        DepartmentVO departmentVO = departmentService.get4appById(departmentId);
        return JsonResult.success(departmentVO);
    }

    @ApiOperation(value = "添加部门架构", notes = "添加")
    @RequestObjectFieldIgnore({"id", "createTime", "remark"})
    @PostMapping("/add")
    public JsonResult add(@Validated(DepartmentForm.Add.class) DepartmentForm departmentForm) {
        try {
            //为终极部门时不允许添加子部门
            if(departmentForm.getParentId() != null){
                Department parent = departmentService.getById(departmentForm.getParentId());
                if(parent != null && parent.getIsFinal() != null && parent.getIsFinal()){
                    return JsonResult.fail("添加失败，该上级部门为终极部门");
                }
            }
            if (departmentService.add(departmentForm) > 0) {
                return JsonResult.success("添加成功");
            }
            return JsonResult.fail("添加失败");
        } catch (BusinessException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }
    @ApiOperation(value = "添加部门架构")
    @RequestObjectFieldIgnore({"id", "createTime", "remark"})
    @PostMapping("/addDepartment")
    public JsonResult addDepartment(@RequestBody DepartmentForm departmentForm) {
        try {
            //为终极部门时不允许添加子部门
            if(departmentForm.getParentId() != null){
                Department parent = departmentService.getById(departmentForm.getParentId());
                if(parent != null && parent.getIsFinal() != null && parent.getIsFinal()){
                    return JsonResult.fail("添加失败，该上级部门为终极部门");
                }
            }
            if (departmentService.add(departmentForm) > 0) {
                return JsonResult.success("添加成功");
            }
            return JsonResult.fail("添加失败");
        } catch (BusinessException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }
    @ApiOperation(value = "修改部门架构")
    @PutMapping("/updateDepartment")
    public JsonResult updateDepartment(@RequestBody DepartmentForm departmentForm) {
        try {
            Department department = departmentService.getById(departmentForm.getId());
            if(department == null){
                return JsonResult.fail("修改失败！");
            }
            if(departmentForm.getParentId()!=null){
                Department parent = departmentService.getById(departmentForm.getParentId());
                if(parent != null && parent.getIsFinal() != null && parent.getIsFinal()){
                    return JsonResult.fail("修改失败，该上级部门为终极部门");
                }
                int count = departmentService.count(new QueryWrapper<Department>().eq("parent_id", department.getId()));
                if(count > 0 && departmentForm.getIsFinal() != null && departmentForm.getIsFinal()){
                    return JsonResult.fail("该部门有下级部门，不可置为终极部门");
                }
            }
            if(departmentForm!=null&&departmentForm.getIsFinal()==null){
                departmentForm.setIsFinal(false);
            }
            CopyOptions copyOptions = CopyOptions.create()
                    .setEditable(Department.class)
                    .setIgnoreError(true)
                    .setIgnoreNullValue(true);
            BeanUtil.copyProperties(departmentForm, department, copyOptions);
            if (departmentService.update(department)) {
                return JsonResult.success("修改成功！");
            }
            return JsonResult.fail("修改失败！");
        } catch (BusinessException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }



    @ApiOperation(value = "修改部门架构", notes = "修改")
    @PutMapping("/update")
    public JsonResult update(@Validated(DepartmentForm.Update.class) DepartmentForm departmentForm) {
        try {
            Department department = departmentService.getById(departmentForm.getId());
            if(department == null){
                return JsonResult.fail("修改失败！");
            }
            if(departmentForm.getParentId()!=null){
                Department parent = departmentService.getById(departmentForm.getParentId());
                if(parent != null && parent.getIsFinal() != null && parent.getIsFinal()){
                    return JsonResult.fail("修改失败，该上级部门为终极部门");
                }
                int count = departmentService.count(new QueryWrapper<Department>().eq("parent_id", department.getId()));
                if(count > 0 && departmentForm.getIsFinal() != null && departmentForm.getIsFinal()){
                    return JsonResult.fail("该部门有下级部门，不可置为终极部门");
                }
            }
            if(departmentForm!=null&&departmentForm.getIsFinal()==null){
                departmentForm.setIsFinal(false);
            }
            CopyOptions copyOptions = CopyOptions.create()
                    .setEditable(Department.class)
                    .setIgnoreError(true)
                    .setIgnoreNullValue(true);
            BeanUtil.copyProperties(departmentForm, department, copyOptions);
            if (departmentService.update(department)) {
                return JsonResult.success("修改成功！");
            }
            return JsonResult.fail("修改失败！");
        } catch (BusinessException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }



    @ApiOperation(value = "删除部门架构", notes = "删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "departmentId", value = "部门架构id", required = true, dataType = "Integer", paramType = "path")
    })
    @DeleteMapping("/{id}" )
    public JsonResult delete(@PathVariable("id") Long departmentId) {
        try {
            if (departmentService.delete(departmentId)) {
                return JsonResult.success("删除成功");
            }
            return JsonResult.fail("删除失败");
        } catch (BusinessException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    @ApiOperation(value="检查唯一性")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code",value = "编码",required = false,dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "id",value = "id",required = false,dataType = "Long",paramType = "query")
    })
    @GetMapping("/isOnly")
    public JsonResult isOnly(@RequestParam(name = "code",required = false) String code,
                             @RequestParam(name="id",required=false) Long id){
        QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(code)){
            queryWrapper.eq("code", code);
        }
        if (id!=null) {
            queryWrapper.ne("id", id);
        }
        int count = departmentService.count(queryWrapper);
        return JsonResult.success(count==0);
    }
    @ApiOperation(value="检查唯一性")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "costCenter",value = "成本中心编码",required = false,dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "id",value = "id",required = false,dataType = "Long",paramType = "query")
    })
    @GetMapping("/isOnlyCostCenter")
    public JsonResult isOnlyCostCenter(@RequestParam(name = "costCenter",required = false) String costCenter,
                             @RequestParam(name="id",required=false) Long id){
        QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(costCenter)){
            queryWrapper.eq("cost_center", costCenter);
        }
        if (id!=null) {
            queryWrapper.ne("id", id);
        }
        int count = departmentService.count(queryWrapper);
        return JsonResult.success(count==0);
    }
    @ApiOperation(value="检查唯一性")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name",value = "名称",required = false,dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "id",value = "id",required = false,dataType = "Long",paramType = "query")
    })
    @GetMapping("/isOnlyName")
    public JsonResult isOnlyName(@RequestParam(name = "name",required = false) String name,
                                       @RequestParam(name="id",required=false) Long id,
                                        @RequestParam(name="companyInfoId",required=false) Long companyInfoId){
        QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(name)){
            queryWrapper.eq("name", name);
        }
        if (id!=null) {
            queryWrapper.ne("id", id);
        }
        if(companyInfoId != null){
            queryWrapper.eq("company_info_id", companyInfoId);
        }
        int count = departmentService.count(queryWrapper);
        return JsonResult.success(count==0);
    }

    /**
     * 下载部门数据录入excel模板
     */
    @ApiOperation(value = "下载部门数据录入excel模板")
    @GetMapping("/template")
    public void template(HttpServletResponse response, HttpServletRequest request) throws IOException {
        String[] headerArr = {"企业","名称","编码","成本中心","上级部门","负责人","是否终级部门"};
        //String[] indexArr = {"0","3","4","5"};
        String[] indexArr = {"0","5","6"};
        List<String[]> downData = new ArrayList<>();
        List<CompanyInfo> list = companyInfoService.list();
        String[] data = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            data[i]=list.get(i).getName();
        }
        downData.add(data);
        List<User> list1 = userService.list();
        String[] data1 = new String[list1.size()];
        for (int i = 0; i < list1.size(); i++) {
            data1[i]=list1.get(i).getUsername();
        }
        downData.add(data1);
        String[] data2 = new String[]{"是","否"};
        downData.add(data2);
        DownExcelUtil.createExcelTemplate(response, request, "部门导入模板", Arrays.asList(headerArr), downData, Arrays.asList(indexArr));
    }

    /**
     * 导入excel
     */
    @ApiOperation(value = "导入excel")
    @PostMapping("/importExcel")
    public JsonResult importExcel(HttpServletRequest request, @RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return JsonResult.fail("导入文件为空！");
        }
        try {
            //获取原始的文件名
            String originalFilename = file.getOriginalFilename();
            String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
            ExcelUtil<DepartmentExcelIn> reader = new ExcelUtil<>();
            InputStream is = file.getInputStream();
            List<DepartmentExcelIn> list = reader.read(is, DepartmentExcelIn.class);
            if (CollectionUtils.isEmpty(list)) {
                return JsonResult.fail("请在表格中添加数据！");
            }
            departmentService.importExcel(list);
        } catch (BusinessException e) {
            log.error("导入文件异常！异常信息:", e);
            return JsonResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            //e.printStackTrace();
            log.error("导入文件异常！异常信息:", e);
            return JsonResult.exception("导入文件异常！异常信息:" + e.getMessage());
        }
        return JsonResult.success("导入成功！");
    }

    @ApiOperation(value = "导出")
    @GetMapping("/export")
    public void export(HttpServletResponse response){
        List<Map<String, Object>> headerList = new ArrayList<>();
        Map<String, Object> headParams = new HashMap();
        headParams.put("name", "名称");
        headParams.put("code", "编码");
        headParams.put("costCenter", "成本中心");
        headParams.put("companyInfoName", "企业");
        headParams.put("parentName", "上级部门");
        headParams.put("isFinalVal", "是否终级部门");
        headParams.put("principal", "负责人");
        headerList.add(headParams);
        Map<String, Object> params = new HashMap();
        List<DepartmentExcelIn> list = departmentService.exportList(params);
        ExcelUtils.export(response, "部门", list, DepartmentExcelIn.class, headerList);
    }

    @ApiOperation(value = "获取所有部门")
    @GetMapping("/getTreeData")
    public JsonResult getTreeData(Long companyId) {
        return departmentService.getTreeData(companyId);
    }

    @ApiOperation(value = "获取所有部门")
    @GetMapping("/getDepartmentList")
    public JsonResult<List<DepartmentVO>> getDepartmentList() {
        Map paramMap=new HashMap();
        paramMap.put("filtrationDepartment",1);
        List<DepartmentVO> list = departmentService.list4app(paramMap);
        return JsonResult.success(list);
    }

    @ApiOperation(value = "获取所有成本中心")
    @GetMapping("/getCostCenterList")
    public JsonResult<List<DepartmentVO>> getCostCenterList() {
        LambdaQueryWrapper<Department> wrapper = new LambdaQueryWrapper<Department>();
        wrapper.isNotNull(Department::getCostCenter);
        return JsonResult.success(departmentService.list(wrapper));
    }
    @GetMapping("/getDepartmentByName")
    public JsonResult<DepartmentVO> getDepartmentByName(@RequestParam(name ="name",required=false)String name
            ,@RequestParam(name = "thirdPartyDepartmentId",required=false)Long thirdPartyDepartmentId
            ,@RequestParam(name = "companyInfoId",required=false)Long companyInfoId) {
        LambdaQueryWrapper<Department> wrapper = new LambdaQueryWrapper<Department>();
        if(StringUtils.isNotBlank(name)){
            wrapper.eq(Department::getName,name);
        }
        if(thirdPartyDepartmentId != null){
            wrapper.eq(Department::getThirdPartyDepartmentId,thirdPartyDepartmentId);
        }
        if(companyInfoId != null){
            wrapper.eq(Department::getCompanyInfoId,companyInfoId);
        }
        Department department = departmentService.getOne(wrapper);
        DepartmentVO departmentVO =new DepartmentVO();
        if(department != null){
            departmentVO.setId(department.getId())
                    .setThirdPartyDepartmentId(department.getThirdPartyDepartmentId())
                    .setName(department.getName());
        }
        return JsonResult.success(departmentVO);
    }

    @ApiOperation(value = "获取部门树形结构")
    @GetMapping("/getDeptTree")
    public JsonResult<List<DepartmentVO>> getDeptTree() {
        return JsonResult.success(departmentService.getDeptTree());
    }
    
}
